package com.hinacom.pix.web.controller;

import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.model.v231.message.ADT_A05;
import ca.uhn.hl7v2.model.v231.message.ADT_A08;
import ca.uhn.hl7v2.model.v231.message.ADT_A40;
import ca.uhn.hl7v2.model.v231.segment.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hinacom.pix.client.PDQConsumer;
import com.hinacom.pix.client.PIXConsumer;
import com.hinacom.pix.client.PIXSource;
import com.hinacom.pix.entity.*;
import com.hinacom.pix.enums.ESex;
import com.hinacom.pix.web.annotation.ResponseJson;
import com.hinacom.pix.web.vo.PixData;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by fyu on 2016/8/19.
 */
@Controller
@RequestMapping("/pix-client")
public class PIXClientController extends BaseController {
    @Autowired
    private HttpServletRequest request;

    @RequestMapping("")
    public ModelAndView index(HttpServletRequest request, HttpServletResponse response) {
        PixData vo = new PixData();
        ModelAndView mv = new ModelAndView("pix-client");
        mv.addObject("vo", vo);
        return mv;
    }

    @RequestMapping("/send")
    public ModelAndView send(String input) throws IOException, HL7Exception, ParseException {
        int s = input.length();

        PixData vo = new PixData();
        ModelAndView mv = new ModelAndView("pix-client");
        mv.addObject("vo", vo);
        vo.setInput(input);

        /*
        Patient patient = this.createPatient();
        PixSource pixSource = new PixSource();
        String output = pixSource.registerInPatient(patient);
        */

        // PIXConsumer pixConsumer = new PIXConsumer();
        // String output = pixConsumer.queryToString(createQuery());
        // vo.setOutput(output);
        // Patient patient = pixConsumer.query(createQuery());

        return mv;
    }

    @RequestMapping("/create-patient")
    public ModelAndView create() {

        ModelAndView mv = new ModelAndView("pix-create");
        return mv;
    }

    @RequestMapping(value = "/create-patient/submit", method = {RequestMethod.POST})
    public ModelAndView createPatientSubmit() throws IOException, HL7Exception, ParseException {
        String json = this.getJsonFromRequest();
        JSONObject jsonObject = JSON.parseObject(json);

        String pid = jsonObject.get("pid").toString();
        String firstName = jsonObject.get("firstName").toString();
        String lastName = jsonObject.get("lastName").toString();
        String action = jsonObject.get("action").toString();
        String city = jsonObject.get("city").toString();

        PIXSource pixSource = new PIXSource();
        Patient sPatient = this.createPatient(pid, firstName, lastName, city);
        String responseMessage = null;
        switch (action) {
            case "Register In Patient":
                responseMessage = pixSource.registerInPatient(sPatient);
                break;
            case "Register Out Patient":
                responseMessage = pixSource.registerOutPatient(sPatient);
                break;
            case "Preregister Patient":
                responseMessage = pixSource.preregisterPatient(sPatient);
                break;
            case "Update Patient":
                responseMessage = pixSource.updatePatient(sPatient);
                break;
            case "Marge Patient":
                Patient mergePatient = this.createPatient(pid, "Miao", lastName, "HangZhou");
                mergePatient.getInternalIdentifier().getAssigningAuthority().setNamespaceId("HinaTest3");
                mergePatient.getInternalIdentifier().getAssigningAuthority().setUniversalId("2.16.840.1.113883.3.72.5.9.1403");
                responseMessage = pixSource.mergePatient(mergePatient, sPatient);
                break;
        }


        /*
        PIXConsumer pixConsumer = new PIXConsumer();
        PIXQueryParameter queryParameter = createQuery();
        Patient sPatient = pixConsumer.query(queryParameter);
        */

        ModelAndView mv = new ModelAndView("pix-create");
        return mv;
    }

    @RequestMapping("/query-patient")
    public ModelAndView query() {
        ModelAndView mv = new ModelAndView("pix-query");
        return mv;
    }


    @RequestMapping("/query-patient/submit")
    public void query(HttpServletRequest request, HttpServletResponse response, @RequestBody HashMap<String, String> map) throws IOException, HL7Exception, ParseException {
        String pid = map.get("PID");
        String domain = map.get("domain");

        /*
        PIXConsumer pixConsumer = new PIXConsumer();
        PIXQueryParameter queryParameter = createQuery(pid, domain);
        ArrayList<String> outPIDList = pixConsumer.query(queryParameter);

        String json = JSON.toJSONString(outPIDList);
        response.setContentType("text/html; charset=UTF-8");
        response.getWriter().print(json);
        response.getWriter().close();
        */

        PDQConsumer pdqConsumer = new PDQConsumer();
        PDQQueryParameter pdqQueryParameter = this.createQueryForPDQ("CAI", "HinaTest3&2.16.840.1.113883.3.72.5.9.1403&ISO");
        String result = pdqConsumer.queryToString(pdqQueryParameter);
        result = "";
    }


    // @RequestBody Patient patient

    @RequestMapping("/create-patient/send")
    public ModelAndView send() {
        ModelAndView mv = new ModelAndView("pix-create");
        return mv;
    }


    @RequestMapping("/general-test")
    public ModelAndView generalTest() {
        ModelAndView mv = new ModelAndView("pix-create");
        return mv;
    }


    private Patient createPatient(String pid, String firstName, String lastName, String city) throws ParseException {
        Patient patient = new Patient();
        PatientIdentifier internalIdentifier = new PatientIdentifier();
        internalIdentifier.setId(pid);

        AssigningAuthority assigningAuthority = AssigningAuthority.createInstanceWithDefualtDomain();
        internalIdentifier.setAssigningAuthority(assigningAuthority);
        patient.setInternalIdentifier(internalIdentifier);

        // patient name
        PatientName patientName = new PatientName();
        patientName.setFirstName(firstName);
        patientName.setLastName(lastName);
        patientName.setMiddleName("MG");
        patient.setPatientName(patientName);

        // mother name
        PatientName motherName = new PatientName();
        motherName.setFirstName("BARNES");
        patient.setMotherName(motherName);

        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.YEAR, -30);
        Date birthDay = calendar.getTime();

        patient.setBirthDay(birthDay);
        patient.setSex(ESex.MALE);

        Address address = new Address();
        address.setStreetAddressLine1("820 JORIE BLVD");
        address.setStreetAddressLine2("DFG Stree");
        address.setCity(city);
        address.setState("Beijing");
        address.setPostalCode("10503");
        address.setCountry("China");
        patient.setAddress(address);
        patient.setSsn("153-12-5432");

        DriversLicense driversLicense = new DriversLicense();
        driversLicense.setLicenseNumber("0002-12332");
        driversLicense.setExpirationDate(birthDay);
        driversLicense.setIssuingState("SA");
        patient.setDriverLicense(driversLicense);
        /*
        PhoneNumber phoneNumber = new PhoneNumber();
        phoneNumber.setExtension("111");
        phoneNumber.setType(PhoneType.HOME);
        phoneNumber.setAreaCode("555");
        phoneNumber.setNote("Home Phone");
        phoneNumber.setCountryCode("1");
        phoneNumber.setEmail("cmic2015@163.com");
        phoneNumber.setNumber("9999999");
        patient.setHomePhoneNumber(phoneNumber);
        */

        PhoneNumber phoneNumber = new PhoneNumber();
        phoneNumber.setExtension("222");
        phoneNumber.setType(PhoneType.WORK);
        phoneNumber.setAreaCode("010");
        phoneNumber.setNote("Work Phone");
        phoneNumber.setCountryCode("81");
        phoneNumber.setEmail("cmic2015@163.com");
        phoneNumber.setNumber("8888888");
        patient.setBusinessPhoneNumber(phoneNumber);


        internalIdentifier = new PatientIdentifier();
        internalIdentifier.setId(pid);

        assigningAuthority = new AssigningAuthority();
        assigningAuthority.setNamespaceId("bank");
        assigningAuthority.setUniversalId("3.16.840.1.113883.3.72.5.9.0001");
        assigningAuthority.setUniversalIDType("ISO");
        internalIdentifier.setAssigningAuthority(assigningAuthority);
        internalIdentifier.setAssigningFacility(assigningAuthority);

        patient.setAccountNumber(internalIdentifier);

        return patient;
    }

    private PIXQueryParameter createQuery(String pid, String domain) {
        String[] domainItems = domain.split("&");
        String namespaceId = domainItems[0];
        String universalId = domainItems[1];
        String universalIDType = domainItems[2];

        PIXQueryParameter queryParameter = new PIXQueryParameter();

        PatientIdentifier patientIdentifier = new PatientIdentifier();
        queryParameter.setParametersInsuccessivefields(patientIdentifier);
        patientIdentifier.setId(pid);
        AssigningAuthority assigningAuthority = new AssigningAuthority();
        patientIdentifier.setAssigningAuthority(assigningAuthority);
        assigningAuthority.setNamespaceId(namespaceId);
        assigningAuthority.setUniversalId(universalId);
        assigningAuthority.setUniversalIDType(universalIDType);

        /*
        assigningAuthority = new AssigningAuthority();
        queryParameter.setFilterDomain(assigningAuthority);
        assigningAuthority.setNamespaceId("HinaTest1");
        assigningAuthority.setUniversalId("2.16.840.1.113883.3.72.5.9.1401");
        assigningAuthority.setUniversalIDType("ISO");
        */
        return queryParameter;
    }

    private PDQQueryParameter createQueryForPDQ(String lastName, String domain) {
        String[] domainItems = domain.split("&");
        String namespaceId = domainItems[0];
        String universalId = domainItems[1];
        String universalIDType = domainItems[2];


        PDQQueryParameter queryParameter = new PDQQueryParameter();
        queryParameter.setReturnRecordCount(100);

        PatientIdentifier patientIdentifier = new PatientIdentifier();

        patientIdentifier.setId("PIXL1");
        AssigningAuthority assigningAuthority = new AssigningAuthority();
        patientIdentifier.setAssigningAuthority(assigningAuthority);
        assigningAuthority.setNamespaceId(namespaceId);
        assigningAuthority.setUniversalId(universalId);
        assigningAuthority.setUniversalIDType(universalIDType);

        // PatientName patientName = new PatientName();
        // patientName.setMiddleName("MG");
        // patientName.setType("L");
        Patient patient = new Patient();

        // patient.setPatientName(patientName);
        Address address = new Address();
        address.setState("Beijing");
        patient.setAddress(address);
        queryParameter.setUserParameters(patient);

        return queryParameter;
    }


    private ADT_A05 getA05Message() throws IOException, HL7Exception {
        ADT_A05 adt = new ADT_A05();
        adt.initQuickstart("ADT", "A05", "P");

        SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");//设置日期格式
        String now = df.format(new Date());
        // Populate the MSH Segment
        MSH mshSegment = adt.getMSH();
        mshSegment.getSendingApplication().getNamespaceID().setValue("HINAPIX");
        mshSegment.getSendingFacility().getHd1_NamespaceID().setValue("Beijing");
        mshSegment.getReceivingApplication().getNamespaceID().setValue("NIST_RCVR_YUMIAO");
        mshSegment.getReceivingFacility().getHd1_NamespaceID().setValue("NIST");
        mshSegment.getMessageControlID().setValue("NIST-101004144709009");
        mshSegment.getDateTimeOfMessage().parse(now);
        mshSegment.getMessageType().getMessageStructure().setValue("ADT_A01");

        EVN evn = adt.getEVN();
        evn.getRecordedDateTime().parse(now);

        // Populate the PID Segment
        PID pid = adt.getPID();
        // patient id
        pid.getPatientIdentifierList(0).getID().setValue("PIX");
        pid.getPatientIdentifierList(0).getAssigningAuthority().getNamespaceID().setValue("NIST2010");
        pid.getPatientIdentifierList(0).getAssigningAuthority().getUniversalID().setValue("2.16.840.1.113883.3.72.5.9.1");
        pid.getPatientIdentifierList(0).getAssigningAuthority().getUniversalIDType().setValue("ISO");

        // patient name
        pid.getPatientName(0).getFamilyLastName().parse("ALPHA");
        pid.getPatientName(0).getGivenName().setValue("ALAN");
        pid.getPatientName(0).getNameTypeCode().setValue("L");

        // mother name
        pid.getMotherSMaidenName(0).getFamilyLastName().parse("BARNES");
        pid.getMotherSMaidenName(0).getGivenName().setValue("");
        pid.getMotherSMaidenName(0).getNameTypeCode().setValue("L");
        pid.getDateTimeOfBirth().parse("19781208");
        pid.getSex().setValue("M");

        pid.getPatientAddress(0).getStreetAddress().parse("820 JORIE BLVD");
        pid.getPatientAddress(0).getCity().setValue("NEW YORK CITY");
        pid.getPatientAddress(0).getStateOrProvince().setValue("NY");
        pid.getPatientAddress(0).getZipOrPostalCode().setValue("10503");

        pid.getSSNNumberPatient().setValue("153-12-5432");

        PV1 pv1 = adt.getPV1();
        pv1.getPatientClass().setValue("P");

        return adt;
    }


    private ADT_A08 getA08Message() throws IOException, HL7Exception {
        ADT_A08 adt = new ADT_A08();
        adt.initQuickstart("ADT", "A08", "P");

        SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");//设置日期格式
        String now = df.format(new Date());
        // Populate the MSH Segment
        MSH mshSegment = adt.getMSH();
        mshSegment.getSendingApplication().getNamespaceID().setValue("HINAPIX");
        mshSegment.getSendingFacility().getHd1_NamespaceID().setValue("Beijing");
        mshSegment.getReceivingApplication().getNamespaceID().setValue("NIST_RCVR_YUMIAO");
        mshSegment.getReceivingFacility().getHd1_NamespaceID().setValue("NIST");
        mshSegment.getMessageControlID().setValue("NIST-101004144709009");
        mshSegment.getDateTimeOfMessage().parse(now);
        mshSegment.getMessageType().getMessageStructure().setValue("ADT_A01");

        EVN evn = adt.getEVN();
        evn.getRecordedDateTime().parse(now);

        // Populate the PID Segment
        PID pid = adt.getPID();
        // patient id
        pid.getPatientIdentifierList(0).getID().setValue("PIX");
        pid.getPatientIdentifierList(0).getAssigningAuthority().getNamespaceID().setValue("NIST2010");
        pid.getPatientIdentifierList(0).getAssigningAuthority().getUniversalID().setValue("2.16.840.1.113883.3.72.5.9.1");
        pid.getPatientIdentifierList(0).getAssigningAuthority().getUniversalIDType().setValue("ISO");

        // patient name
        pid.getPatientName(0).getFamilyLastName().parse("TAU");
        pid.getPatientName(0).getGivenName().setValue("TERI");
        pid.getPatientName(0).getNameTypeCode().setValue("L");


        pid.getDateTimeOfBirth().parse("19781208");
        pid.getSex().setValue("M");

        pid.getPatientAddress(0).getStreetAddress().parse("202 KEN HABOR");
        pid.getPatientAddress(0).getCity().setValue("NEW YORK CITY");
        pid.getPatientAddress(0).getStateOrProvince().setValue("NY");
        pid.getPatientAddress(0).getZipOrPostalCode().setValue("61000");

        PV1 pv1 = adt.getPV1();
        pv1.getPatientClass().setValue("R");

        return adt;
    }

    private ADT_A40 getA40Message() throws IOException, HL7Exception {
        ADT_A40 adt = new ADT_A40();
        adt.initQuickstart("ADT", "A40", "P");

        SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");//设置日期格式
        String now = df.format(new Date());
        // Populate the MSH Segment
        MSH mshSegment = adt.getMSH();
        mshSegment.getSendingApplication().getNamespaceID().setValue("HINAPIX");
        mshSegment.getSendingFacility().getHd1_NamespaceID().setValue("Beijing");
        mshSegment.getReceivingApplication().getNamespaceID().setValue("NIST_RCVR_YUMIAO");
        mshSegment.getReceivingFacility().getHd1_NamespaceID().setValue("NIST");
        mshSegment.getMessageControlID().setValue("NIST-101004144709009");
        mshSegment.getDateTimeOfMessage().parse(now);
        mshSegment.getMessageType().getMessageStructure().setValue("ADT_A39");

        EVN evn = adt.getEVN();
        evn.getRecordedDateTime().parse(now);

        // Populate the PID Segment
        PID pid = adt.getPIDPD1MRGPV1().getPID();
        // patient id
        pid.getPatientIdentifierList(0).getID().setValue("PIX");
        pid.getPatientIdentifierList(0).getAssigningAuthority().getNamespaceID().setValue("NIST2010");
        pid.getPatientIdentifierList(0).getAssigningAuthority().getUniversalID().setValue("2.16.840.1.113883.3.72.5.9.1");
        pid.getPatientIdentifierList(0).getAssigningAuthority().getUniversalIDType().setValue("ISO");

        // patient name
        pid.getPatientName(0).getFamilyLastName().parse("LINCOLN");
        pid.getPatientName(0).getGivenName().setValue("MARY");
        pid.getPatientName(0).getNameTypeCode().setValue("L");


        MRG mgr = adt.getPIDPD1MRGPV1().getMRG();
        mgr.getMrg1_PriorPatientIdentifierList(0).getID().setValue("PIXW");
        mgr.getMrg1_PriorPatientIdentifierList(0).getAssigningAuthority().getNamespaceID().setValue("NIST2010");
        mgr.getMrg1_PriorPatientIdentifierList(0).getAssigningAuthority().getUniversalID().setValue("2.16.840.1.113883.3.72.5.9.1");
        mgr.getMrg1_PriorPatientIdentifierList(0).getAssigningAuthority().getUniversalIDType().setValue("ISO");

        mgr.getMrg7_PriorPatientName(0).getFamilyLastName().parse("WASHINGTON");
        mgr.getMrg7_PriorPatientName(0).getGivenName().parse("WASHINGTON");
        mgr.getMrg7_PriorPatientName(0).getNameTypeCode().setValue("L");
        return adt;
    }


    private String getJsonFromRequest() throws IOException {
        String json = null;
        if (StringUtils.isNotEmpty(request.getContentType())
                && request.getContentType().contains("application/json")) {
            InputStream inputStream = request.getInputStream();
            Scanner scanner = new Scanner(inputStream, "UTF-8");
            json = scanner.useDelimiter("\\A").next();
        }
        return json;
    }
}
